vlwkaos' digital garden

JavaScript - Event Bubbling VS Event Capturing

3줄 요약:

  1. Capturing 단계: 발생한 이벤트는 하위 Element로 전달된다.
  2. Target 단계: 이벤트에 대한 처리가 있는 가장 깊숙한 Element에 도달. event.target
  3. Bubbling 단계: 상위 Element로 올라가며 이벤트에 대한 처리를 한다. event.currentTarget

Bubbling

한 Element에 이벤트가 발생하면, 그 Element를 포함한 상위 Element의 이벤트 처리기도 연달아 동작한다.

예를 들어, 아래 같은 구조가 있을 때 <p>에 해당하는 영역을 클릭하면, p, div, form 가 찍힌 알림창이 순차적으로 열린다.

<form onclick="alert('form')">
  FORM
  <div onclick="alert('div')">
    DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>

event.target

event.target은 이벤트가 발생한 가장 깊숙히 있는 Element를 참조한다.

this와 햇갈리지 않도록 주의하자 (=event.currentTarget):

  • event.target 은 앞서 말했듯 이벤트가 발생한 Element이므로 버블링을 통해 이벤트 핸들러 동작이 실행될 때도 변하지 않는다.
  • this 현재 이벤트를 처리중인 Element를 참조한다.

Bubbling 멈춰!

Bubbling은 결국 HTML 문서의 최상위 Element인 <html>까지 올라가고 document 객체를 거쳐서 가끔은 window까지도 도달한다.

더이상 Bubbling을 통한 처리를 원치 않는 경우event.stopPropagation()을 호출할 수 있다.

ℹ️ 만약 하나의 이벤트에 의해 여러 처리가 발생하는 경우 위의 방법으로 Bubbling을 중단할 수 없다. 현재 Element에 대해 Bubbling을 막는 동시에 모든 이벤트 처리도 중단하려면 event.stopImmeditatePropagation()을 이용해야한다.

⚠️ Bubbling을 멈추는 것은 정말 필요에 의해서 정교하게 이뤄져야한다. 대부분의 경우 Bubbling은 도움이 된다. 가령 이런 상황이 있을 수 있다.

  1. 메뉴안에 하위 메뉴가있는 형태의 UI를 만들었을 때 각 하위 메뉴는 클릭 이벤트를 처리하고 Bubbling을 하지 않도록 처리했다고 하자.
  2. 나중에 요구사항에 의해 메뉴 전체 클릭을 감지해야하는 상황이 발생했을 때 하위 메뉴의 Bubbling중단에 의해 메뉴에 부착된 이벤트 처리가 불가능한 영역이 생겨버린다.

Capturing

DOM Event는 다음 과정을 거쳐서 Event를 전달한다.

  1. Capturing 단계 - 이벤트가 상위 Element부터 아래로 전달된다.
  2. Target 단계 - 이벤트 처리를 하는 Element에 도달했다.
  3. Bubbling 단계 - Target Element부터 상위로 올라가며 이벤트에 대한 처리를 한다.

일반적으로 Capturing은 숨겨져있다. 이것을 직접 보기 위해서는 이벤트에 대한 처리를 추가할 때 의도적으로 옵션을 주어야한다.

elem.addEventListener(..., {capture: true});
elem.addEventListener(..., true); // 더 간략한 버전

ℹ️ 이벤트 Capturing하는 이벤트 처리를 추가했다면 제거할 때도 동일한 옵션을 주어야 제대로 제거가된다. removeEventListener(..., true)

JavaScript - Event Bubbling VS Event Capturing